home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / xvctrl.c < prev    next >
C/C++ Source or Header  |  1992-01-02  |  19KB  |  640 lines

  1. /* 
  2.  * xvctrl.c - Control box handling functions
  3.  *
  4.  * callable functions:
  5.  *
  6.  *   CreateCtrl(geom)       -  creates the ctrlW window.  Doesn't map it.
  7.  *   CtrlBox(vis)           -  random processing based on value of 'vis'
  8.  *                             maps/unmaps window, etc.
  9.  *   RedrawCtrl(x,y,w,h)    -  called by 'expose' events
  10.  *   ClickCtrl(x,y)
  11.  *   DrawCtrlStr()          -  called to redraw 'ISTR_INFO' string in ctrlW
  12.  *   ScrollToCurrent()      -  called when 'curname' is changed 
  13.  *
  14.  *   LSCreate()             -  creates a listbox
  15.  *   LSRedraw()             -  redraws 'namelist' box
  16.  *   LSClick()              -  operates list box
  17.  *   LSNewData()            -  called when strings or number of them change
  18.  *   LSKey()                -  called to handle page up/down, arrows
  19.  *
  20.  */
  21.  
  22. /*
  23.  * Copyright 1989, 1990, 1991, 1992 by John Bradley and
  24.  *                       The University of Pennsylvania
  25.  *
  26.  * Permission to use, copy, and distribute for non-commercial purposes,
  27.  * is hereby granted without fee, providing that the above copyright
  28.  * notice appear in all copies and that both the copyright notice and this
  29.  * permission notice appear in supporting documentation. 
  30.  *
  31.  * The software may be modified for your own purposes, but modified versions
  32.  * may not be distributed.
  33.  *
  34.  * This software is provided "as is" without any expressed or implied warranty.
  35.  *
  36.  * The author may be contacted via:
  37.  *    US Mail:   John Bradley
  38.  *               GRASP Lab, Room 301C
  39.  *               3401 Walnut St.  
  40.  *               Philadelphia, PA  19104
  41.  *
  42.  *    Phone:     (215) 898-8813
  43.  *    EMail:     bradley@cis.upenn.edu       
  44.  */
  45.  
  46.  
  47.  
  48. #include "xv.h"
  49. #include "bitmaps.h"
  50.  
  51. #define DBLCLKTIME 500             /* double-click speed in milliseconds */
  52.  
  53. #define INACTIVE(lptr, item) ((lptr)->filetypes && (lptr)->dirsonly && \
  54.                   (item) >= 0 && (item) < (lptr)->nstr && \
  55.                   (lptr)->str[(item)][0] != C_DIR && \
  56.                   (lptr)->str[(item)][0] != C_LNK)
  57.  
  58. #define NLINES 9                   /* # of lines in list control (keep odd) */
  59. #define LISTW CTRL_LISTW
  60.  
  61. #define BUTTW   71   /* must be odd for 'half' buttons to work out */
  62. #define BUTTH   24
  63.  
  64. static int    listh;               /* height of list/scrl controls */
  65. static int    ptop;                /* y-coord of top of button area in ctrlW */
  66.  
  67. static Pixmap fifoPix, chrPix, dirPix, blkPix, lnkPix, sockPix, regPix;
  68. static Pixmap rotlPix, rotrPix;
  69.  
  70. static XRectangle butrect;
  71.  
  72. static char *dispMList[] = { "Window", 
  73.                  "Root: tiled",
  74.                  "Root: integer tiled",
  75.                  "Root: mirrored",
  76.                  "Root: integer mirrored",
  77.                  "Root: center tiled",
  78.                  "Root: centered",
  79.                  "Root: centered, warp",
  80.                  "Root: centered, brick" };
  81.  
  82.  
  83. #ifdef __STDC__
  84. static void drawSel(LIST *, int);
  85. static void RedrawNList(void);
  86. #else
  87. static void drawSel(), RedrawNList();
  88. #endif
  89.  
  90.  
  91. /***************************************************/
  92. void CreateCtrl(geom)
  93. char *geom;
  94. {
  95.   int i,b2wide;
  96.   XClassHint classh;
  97.   CARD32     data[2];
  98.   Atom       prop;
  99.  
  100.  
  101.   ctrlW = CreateWindow("xv controls", geom, CTRLWIDE,CTRLHIGH,infofg,infobg);
  102.   if (!ctrlW) FatalError("can't create controls window!");
  103.  
  104.   classh.res_name = "xv";
  105.   classh.res_class = "XVcontrols";
  106.   XSetClassHint(theDisp, ctrlW, &classh);
  107.  
  108.   data[0] = (CARD32)XInternAtom(theDisp, "WM_DELETE_WINDOW", FALSE);
  109.   data[1] = (CARD32)time((long *)0);
  110.   prop = XInternAtom(theDisp, "WM_PROTOCOLS", FALSE),
  111.  
  112.   XChangeProperty(theDisp, ctrlW, prop, prop,
  113.           32, PropModeReplace, (unsigned char *) data, 2);
  114.  
  115.   grayTile = XCreatePixmapFromBitmapData(theDisp, ctrlW, gray25_bits,
  116.          gray25_width, gray25_height, infofg, infobg, dispDEEP);
  117.  
  118.   grayStip = XCreatePixmapFromBitmapData(theDisp, ctrlW, gray50_bits,
  119.          gray50_width, gray50_height, 1, 0, 1);
  120.   
  121.   fifoPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_fifo_bits,
  122.          i_fifo_width, i_fifo_height, 1, 0, 1);
  123.   
  124.   chrPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_chr_bits,
  125.          i_chr_width, i_chr_height, 1,0,1);
  126.   
  127.   dirPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_dir_bits,
  128.          i_dir_width, i_dir_height, 1,0,1);
  129.   
  130.   blkPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_blk_bits,
  131.          i_blk_width, i_blk_height, 1,0,1);
  132.   
  133.   lnkPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_lnk_bits,
  134.          i_lnk_width, i_lnk_height, 1,0,1);
  135.   
  136.   sockPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_sock_bits,
  137.          i_sock_width, i_sock_height, 1,0,1);
  138.   
  139.   regPix  = XCreatePixmapFromBitmapData(theDisp, ctrlW, i_reg_bits,
  140.          i_reg_width, i_reg_height, 1,0,1);
  141.  
  142.   rotlPix = XCreatePixmapFromBitmapData(theDisp, ctrlW, h_rotl_bits, 
  143.                     h_rotl_width, h_rotl_height, 1, 0, 1);
  144.  
  145.   rotrPix = XCreatePixmapFromBitmapData(theDisp, ctrlW, h_rotr_bits, 
  146.                     h_rotr_width, h_rotr_height, 1, 0, 1);
  147.  
  148.   
  149.  
  150.   if (ctrlColor) XSetWindowBackground(theDisp, ctrlW, locol);
  151.             else XSetWindowBackgroundPixmap(theDisp, ctrlW, grayTile);
  152.  
  153.   /* create doo-wahs */
  154.   listh = LINEHIGH * NLINES;
  155.  
  156.   LSCreate(&nList, ctrlW, 10, 10+CHIGH+1, LISTW, listh, NLINES, dispnames, 
  157.        numnames, infofg, infobg, RedrawNList, 0, 0);
  158.   nList.selected = 0;  /* default to first name selected */
  159.  
  160.   i = listh-BUTTH;
  161.  
  162.   BTCreate(&but[BNEXT], ctrlW, 298, 12+nList.y+(i*1)/8, 60, 
  163.        BUTTH, "Next",     infofg, infobg);
  164.   BTCreate(&but[BPREV], ctrlW, 298, 12+nList.y+(i*3)/8, 60, 
  165.        BUTTH, "Previous", infofg, infobg);
  166.   BTCreate(&but[BINFO], ctrlW, 298, 12+nList.y+(i*5)/8, 60, 
  167.        BUTTH, "Info", infofg, infobg);
  168.   BTCreate(&but[BGAMMA], ctrlW,298, 12+nList.y+(i*7)/8, 60, 
  169.        BUTTH, "ColEdit", infofg, infobg);
  170.  
  171.   BTCreate(&but[BLOAD],   ctrlW, 368, 12+nList.y+(i*1)/8, 60, 
  172.        BUTTH, "Load",     infofg, infobg);
  173.   BTCreate(&but[BSAVE],   ctrlW, 368, 12+nList.y+(i*3)/8, 60, 
  174.        BUTTH, "Save",     infofg, infobg);
  175.   BTCreate(&but[BDELETE], ctrlW, 368, 12+nList.y+(i*5)/8, 60, 
  176.        BUTTH, "Delete", infofg, infobg);
  177.   BTCreate(&but[BQUIT],   ctrlW, 368, 12+nList.y+(i*7)/8, 60, 
  178.        BUTTH, "Quit", infofg, infobg);
  179.  
  180.  
  181. #define BXSPACE (BUTTW+1)
  182. #define BYSPACE (BUTTH+1)
  183.  
  184.   ptop = CTRLHIGH - (3*BYSPACE + 5 + 4);
  185.  
  186. #define BX0 ((CTRLWIDE - (BXSPACE*6))/2)
  187. #define BX1 (BX0 + BXSPACE)
  188. #define BX2 (BX0 + BXSPACE*2)
  189. #define BX3 (BX0 + BXSPACE*3)
  190. #define BX4 (BX0 + BXSPACE*4)
  191. #define BX5 (BX0 + BXSPACE*5)
  192. #define BY0 (ptop+5)
  193. #define BY1 (BY0 + BYSPACE)
  194. #define BY2 (BY0 + BYSPACE*2)
  195.  
  196.   butrect.x = BX0-1;  butrect.y = BY0-1;
  197.   butrect.width = 6*BXSPACE + 1;
  198.   butrect.height = 3*BYSPACE + 1;
  199.  
  200.   BTCreate(&but[BCROP],   ctrlW,BX0,BY0,BUTTW,BUTTH,"Crop",     infofg,infobg);
  201.   BTCreate(&but[BUNCROP], ctrlW,BX0,BY1,BUTTW,BUTTH,"UnCrop",   infofg,infobg);
  202.   BTCreate(&but[BACROP],  ctrlW,BX0,BY2,BUTTW,BUTTH,"AutoCrop", infofg,infobg);
  203.  
  204.   BTCreate(&but[BNORM],   ctrlW,BX1,BY0,BUTTW,BUTTH,"Normal",   infofg,infobg);
  205.   BTCreate(&but[BMAX],    ctrlW,BX1,BY1,BUTTW,BUTTH,"Max Size", infofg,infobg);
  206.   BTCreate(&but[BMAXPECT],ctrlW,BX1,BY2,BUTTW,BUTTH,"Maxpect",  infofg,infobg);
  207.  
  208.   BTCreate(&but[BUP2],    ctrlW,BX2,BY0,BUTTW,BUTTH,"Dbl Size", infofg,infobg);
  209.   BTCreate(&but[BDN2],    ctrlW,BX2,BY1,BUTTW,BUTTH,"Half Size",infofg,infobg);
  210.   BTCreate(&but[B4BY3],   ctrlW,BX2,BY2,BUTTW,BUTTH,"4x3",      infofg,infobg);
  211.  
  212.   BTCreate(&but[BUP10],   ctrlW,BX3,BY0,BUTTW,BUTTH,"+10%",     infofg,infobg);
  213.   BTCreate(&but[BDN10],   ctrlW,BX3,BY1,BUTTW,BUTTH,"-10%",     infofg,infobg);
  214.   BTCreate(&but[BASPECT], ctrlW,BX3,BY2,BUTTW,BUTTH,"Aspect",   infofg,infobg);
  215.  
  216.   BTCreate(&but[BRAW],    ctrlW,BX4,BY0,BUTTW,BUTTH,"Raw",      infofg,infobg);
  217.   BTCreate(&but[BDITH],   ctrlW,BX4,BY1,BUTTW,BUTTH,"Dither",   infofg,infobg);
  218.   BTCreate(&but[BSMOOTH], ctrlW,BX4,BY2,BUTTW,BUTTH,"Smooth",   infofg,infobg);
  219.  
  220.   BTCreate(&but[BROTL],    ctrlW,BX5,BY0,BUTTW/2,BUTTH,
  221.        "", infofg,infobg);
  222.   BTCreate(&but[BROTR],    ctrlW,BX5+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH,
  223.        "", infofg,infobg);
  224.  
  225.   BTCreate(&but[BFLIPH],   ctrlW,BX5,BY1,BUTTW,BUTTH,"Flip H",  infofg,infobg);
  226.   BTCreate(&but[BFLIPV],   ctrlW,BX5,BY2,BUTTW,BUTTH,"Flip V",  infofg,infobg);
  227.  
  228.  
  229.   but[BROTL].pix = rotlPix;
  230.   but[BROTL].pw  = h_rotl_width;
  231.   but[BROTL].ph  = h_rotl_height;
  232.  
  233.   but[BROTR].pix = rotrPix;
  234.   but[BROTR].pw  = h_rotr_width;
  235.   but[BROTR].ph  = h_rotr_height;
  236.  
  237.   if (numnames<1) BTSetActive(&but[BDELETE],0);
  238.  
  239.   XMapSubwindows(theDisp, ctrlW);
  240.  
  241.   /* have to create dispMB after XMapSubWindows, as we *don't* want the popup
  242.      mapped */
  243.  
  244.   MBCreate(&dispMB, ctrlW, 298, but[BNEXT].y - 19 - 8, 128, 19,
  245.        "Display Modes", dispMList, RM_MAX+2, infofg, infobg);
  246.  
  247.   if (!useroot) dispMB.selected = 0;
  248.            else dispMB.selected = rootMode + 1;
  249. }
  250.   
  251.  
  252. /***************************************************/
  253. void CtrlBox(vis)
  254. int vis;
  255. {
  256.   if (vis) XMapRaised(theDisp, ctrlW);
  257.   else     XUnmapWindow(theDisp, ctrlW);
  258.  
  259.   ctrlUp = vis;
  260. }
  261.  
  262.  
  263. /***************************************************/
  264. void RedrawCtrl(x,y,w,h)
  265. int x,y,w,h;
  266. {
  267.   char foo[40];
  268.   int i;
  269.   XRectangle xr;
  270.  
  271.   xr.x = x;  xr.y = y;  xr.width = w;  xr.height = h;
  272.   XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
  273.  
  274.   XSetForeground(theDisp, theGC, infofg);
  275.   XSetBackground(theDisp, theGC, infobg);
  276.  
  277.   XDrawLine(theDisp, ctrlW, theGC, 0, ptop, CTRLWIDE, ptop);
  278.  
  279.   if (numnames != 1) sprintf(foo,"%d files",numnames);
  280.   else strcpy(foo,"1 file");
  281.     
  282.   XSetForeground(theDisp, theGC, infobg);
  283.   XFillRectangle(theDisp,ctrlW, theGC, 10+1,5+1,StringWidth(foo)+4,CHIGH+2);
  284.   XSetForeground(theDisp,theGC,infofg);
  285.   XDrawRectangle(theDisp,ctrlW, theGC, 10,5,StringWidth(foo)+5,CHIGH+3);
  286.   XDrawString(theDisp, ctrlW, theGC, 10+3, 5+ASCENT+2,
  287.           foo, strlen(foo));
  288.  
  289.   XSetForeground(theDisp,theGC,infofg);
  290.   XDrawRectangles(theDisp, ctrlW, theGC, &butrect, 1);
  291.  
  292.   for (i=0; i<NBUTTS; i++)
  293.     BTRedraw(&but[i]);
  294.  
  295.   MBRedraw(&dispMB);
  296.  
  297.   DrawCtrlStr();
  298.  
  299.   XSetClipMask(theDisp, theGC, None);
  300. }
  301.  
  302.  
  303. /***************************************************/
  304. void DrawCtrlStr()
  305. {
  306.   int   y;
  307.   char *st,*st1;
  308.  
  309.   y = ptop - (CHIGH + 4)*2 - 2;
  310.   st  = GetISTR(ISTR_INFO);
  311.   st1 = GetISTR(ISTR_WARNING);
  312.  
  313.   XSetForeground(theDisp, theGC, infobg);
  314.   XFillRectangle(theDisp, ctrlW, theGC, 0, y+1, CTRLWIDE, (CHIGH+4)*2+1);
  315.  
  316.   XSetForeground(theDisp, theGC, infofg);
  317.   XDrawLine(theDisp, ctrlW, theGC, 0, y,   CTRLWIDE, y);
  318.   XDrawLine(theDisp, ctrlW, theGC, 0, y+2, CTRLWIDE, y+2);
  319.   XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+4, CTRLWIDE, y+CHIGH+4);
  320.   XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+6, CTRLWIDE, y+CHIGH+6);
  321.   XDrawLine(theDisp, ctrlW, theGC, 0, y+(CHIGH+4)*2, CTRLWIDE, y+(CHIGH+4)*2);
  322.  
  323.   XDrawString(theDisp, ctrlW, theGC, 10, y+ASCENT+3,       st, strlen(st));
  324.   XDrawString(theDisp, ctrlW, theGC, 10, y+ASCENT+CHIGH+7, st1, strlen(st1));
  325. }
  326.  
  327.  
  328. /***************************************************/
  329. int ClickCtrl(x,y)
  330. int x,y;
  331. {
  332.   BUTT *bp;
  333.   int   i;
  334.  
  335.   for (i=0; i<NBUTTS; i++) {
  336.     bp = &but[i];
  337.     if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
  338.   }
  339.  
  340.   if (i<NBUTTS) {                   /* found one */
  341.     if (BTTrack(bp)) return (i);    /* and it was clicked */
  342.   }
  343.  
  344.   return -1;
  345. }
  346.  
  347.  
  348.  
  349. /***************************************************/
  350. void ScrollToCurrent(lst)
  351. LIST *lst;
  352. {
  353.   /* called when 'curname' is changed by anything (next/prev buttons,
  354.      wait timeout, whatever.  IF curname is already visible, just redraws
  355.      list to reflect changed selection.  If not, trys to adjust 'liststart' 
  356.      so that curname will appear in the center of the list window */
  357.  
  358.   int halfway;
  359.  
  360.   if (lst->selected > lst->scrl.val && 
  361.       lst->selected <  lst->scrl.val + lst->nlines-1) LSRedraw(lst);
  362.   else {
  363.     halfway = (lst->nlines)/2;   /* offset to the halfway pt. of the list */
  364.     if (!SCSetVal(&lst->scrl, lst->selected - halfway)) LSRedraw(lst);
  365.   }
  366. }
  367.  
  368.  
  369. /***************************************************/
  370. static void RedrawNList()
  371. {
  372.   LSRedraw(&nList);
  373. }
  374.  
  375.  
  376.  
  377.  
  378. /***************** LIST STUFF *********************/
  379.  
  380. /***************************************************/
  381. void LSCreate(lp, win, x, y, w, h, nlines, strlist, nstr, fg, bg, fptr, 
  382.           typ, donly)
  383. LIST         *lp;
  384. Window        win;
  385. int           x,y,w,h,nlines,nstr,typ,donly;
  386. unsigned long fg, bg;
  387. char        **strlist;    /* a pointer to a list of strings */
  388. void        (*fptr)();
  389. {
  390.   lp->win = XCreateSimpleWindow(theDisp,win,x,y,w,h,1,infofg,infobg);
  391.   if (!lp->win) FatalError("can't create list window!");
  392.  
  393.   lp->x = x;    lp->y = y;   
  394.   lp->w = w;    lp->h = h;
  395.   lp->fg = fg;  lp->bg = bg;
  396.   lp->str      = strlist;
  397.   lp->nstr     = nstr;
  398.   lp->selected = -1;   /* no initial selection */
  399.   lp->nlines   = nlines;
  400.   lp->filetypes= typ;
  401.   lp->dirsonly = donly;
  402.  
  403.   XSelectInput(theDisp, lp->win, ExposureMask | ButtonPressMask);
  404.  
  405.   SCCreate(&lp->scrl, win, x+w, y, 1, h, 0, nstr-nlines, curname, nlines-1,
  406.        fg, bg, fptr);
  407. }
  408.  
  409.  
  410.  
  411. /***************************************************/
  412. void LSNewData(lp, strlist, nstr)
  413. LIST         *lp;
  414. char        **strlist;
  415. int           nstr;
  416. {
  417.   lp->str = strlist;
  418.   lp->nstr = nstr;
  419.   lp->selected = -1;   /* no initial selection */
  420.   SCSetRange(&lp->scrl, 0, nstr - lp->nlines, 0, lp->nlines-1);
  421. }
  422.  
  423.  
  424. /***************************************************/
  425. static void drawSel(lp,j)
  426. LIST *lp;
  427. int j;
  428. {
  429.   int i, inactive;
  430.   unsigned long fg, bg;
  431.  
  432.   inactive = INACTIVE(lp,j);
  433.  
  434.   i = j - lp->scrl.val;
  435.   if (i<0 || i>=lp->nlines) return;  /* off screen */
  436.  
  437.   if (j == lp->selected && !inactive && j<lp->nstr) 
  438.        { fg = lp->bg;  bg = lp->fg; }  /* invert */
  439.   else { fg = lp->fg;  bg = lp->bg; }
  440.  
  441.   XSetForeground(theDisp, theGC, bg);
  442.   XFillRectangle(theDisp, lp->win, theGC, 0,i*LINEHIGH, lp->w, LINEHIGH);
  443.  
  444.   if (j>=0 && j<lp->nstr) {   /* only draw string if valid */
  445.     /* make non-dirs inactive, if dirsonly and filetypes */
  446.     XSetForeground(theDisp, theGC, fg);
  447.     XSetBackground(theDisp, theGC, bg);
  448.  
  449.     if (!lp->filetypes) 
  450.       XDrawString(theDisp, lp->win, theGC, 3, i*LINEHIGH + ASCENT + 1, 
  451.           lp->str[j], strlen(lp->str[j]));
  452.     else {
  453.       int ypos = i*LINEHIGH + (LINEHIGH - i_fifo_height)/2;
  454.  
  455.       if (lp->str[j][0] == C_FIFO) 
  456.     XCopyPlane(theDisp, fifoPix, lp->win, theGC, 0, 0,
  457.            i_fifo_width, i_fifo_height, 3, ypos, 1L);
  458.  
  459.       else if (lp->str[j][0] == C_CHR) 
  460.     XCopyPlane(theDisp, chrPix, lp->win, theGC, 0, 0,
  461.            i_chr_width, i_chr_height, 3, ypos, 1L);
  462.  
  463.       else if (lp->str[j][0] == C_DIR) 
  464.     XCopyPlane(theDisp, dirPix, lp->win, theGC, 0, 0,
  465.            i_dir_width, i_dir_height, 3, ypos, 1L);
  466.  
  467.       else if (lp->str[j][0] == C_BLK) 
  468.     XCopyPlane(theDisp, blkPix, lp->win, theGC, 0, 0,
  469.            i_blk_width, i_blk_height, 3, ypos, 1L);
  470.  
  471.       else if (lp->str[j][0] == C_LNK) 
  472.     XCopyPlane(theDisp, lnkPix, lp->win, theGC, 0, 0,
  473.            i_lnk_width, i_lnk_height, 3, ypos, 1L);
  474.  
  475.       else if (lp->str[j][0] == C_SOCK) 
  476.     XCopyPlane(theDisp, sockPix, lp->win, theGC, 0, 0,
  477.            i_sock_width, i_sock_height, 3, ypos, 1L);
  478.  
  479.       else  /* lp->str[j][0] == C_REG */
  480.     XCopyPlane(theDisp, regPix, lp->win, theGC, 0, 0,
  481.            i_reg_width, i_reg_height, 3, ypos, 1L);
  482.  
  483.  
  484.       XDrawString(theDisp, lp->win, theGC, 3 + i_fifo_width + 3, 
  485.           i*LINEHIGH + ASCENT + 1, 
  486.           lp->str[j]+1, strlen(lp->str[j]+1));
  487.     }
  488.   }
  489. }
  490.  
  491.  
  492. /***************************************************/
  493. void LSRedraw(lp)
  494. LIST *lp;
  495. {
  496.   int  i;
  497.  
  498.   for (i = lp->scrl.val; i < lp->scrl.val + lp->nlines; i++) 
  499.     drawSel(lp,i);
  500. }
  501.  
  502.  
  503. /***************************************************/
  504. int LSClick(lp,ev)
  505. LIST *lp;
  506. XButtonEvent *ev;
  507. {
  508.   /* returns '-1' normally.  returns 0 -> numnames-1 for a goto */
  509.  
  510.   Window       rW, cW;
  511.   int          rx, ry, x, y, sel, oldsel;
  512.   unsigned int mask;
  513.   static Time  lasttime=0;
  514.   static int   lastsel = -1;
  515.  
  516.   x = ev->x;  y = ev->y;
  517.   sel = lp->scrl.val + y/LINEHIGH;
  518.   if (sel >= lp->nstr) sel = lp->selected;
  519.  
  520.   /* see if it's a double click */
  521.   if (ev->time - lasttime < DBLCLKTIME && sel==lastsel 
  522.       && (lp->scrl.val + y/LINEHIGH) < lp->nstr
  523.       && !INACTIVE(lp,sel)) {
  524.     return (sel);
  525.   }
  526.  
  527.   lasttime = ev->time;  lastsel = sel;
  528.  
  529.   /* if not clicked on selected, turn off selected and select new one */
  530.   if (sel != lp->selected) {
  531.     oldsel = lp->selected;
  532.     lp->selected = sel;
  533.     drawSel(lp,sel);  drawSel(lp,oldsel);
  534.     XFlush(theDisp);
  535.   }
  536.  
  537.   while (XQueryPointer(theDisp,lp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
  538.     if (!(mask & Button1Mask)) break;    /* button released */
  539.  
  540.     if (y<0) { /* scroll up in list */ 
  541.       if (lp->scrl.val > lp->scrl.min) {
  542.     lp->selected = lp->scrl.val - 1;
  543.     SCSetVal(&lp->scrl, lp->scrl.val - 1);
  544.     Timer(100);
  545.       }
  546.     }
  547.  
  548.     else if (y > lp->h) { /* scroll down in list */
  549.       if (lp->scrl.val < lp->scrl.max) {
  550.     lp->selected = lp->scrl.val + lp->nlines;
  551.     if (lp->selected >= lp->nstr) lp->selected = lp->nstr - 1;
  552.     SCSetVal(&lp->scrl, lp->scrl.val + 1);
  553.     Timer(100);
  554.       }
  555.     }
  556.  
  557.     else {
  558.       sel = lp->scrl.val + y/LINEHIGH;
  559.       if (sel >= lp->nstr) sel = lp->nstr - 1;
  560.  
  561.       if (sel != lp->selected && sel >= lp->scrl.val &&
  562.       sel < lp->scrl.val + lp->nlines) {  
  563.     /* dragged to another on current page */
  564.     oldsel = lp->selected;
  565.     lp->selected = sel;
  566.     drawSel(lp, sel);  drawSel(lp, oldsel);
  567.     XFlush(theDisp);
  568.       }
  569.     }
  570.   }
  571.  
  572.   return(-1);
  573. }
  574.  
  575.  
  576.  
  577. /***************************************************/
  578. void LSKey(lp, key)
  579. LIST         *lp;
  580. int           key;
  581. {
  582.   if      (key==LS_PAGEUP)   SCSetVal(&lp->scrl,lp->scrl.val - (lp->nlines-1));
  583.   else if (key==LS_PAGEDOWN) SCSetVal(&lp->scrl,lp->scrl.val + (lp->nlines-1));
  584.   else if (key==LS_HOME)     SCSetVal(&lp->scrl,lp->scrl.min);
  585.   else if (key==LS_END)      SCSetVal(&lp->scrl,lp->scrl.max);
  586.  
  587.   else if (key==LS_LINEUP)   {
  588.     /* if the selected item visible, but not the top line */
  589.     if (lp->selected > lp->scrl.val && 
  590.     lp->selected <= lp->scrl.val + lp->nlines - 1) {
  591.       /* then just move it */
  592.       lp->selected--;
  593.       drawSel(lp, lp->selected);  drawSel(lp, lp->selected+1);
  594.     }
  595.  
  596.     /* if it's the top line... */
  597.     else if (lp->selected == lp->scrl.val) {
  598.       if (lp->selected > 0) {
  599.     lp->selected--;
  600.     SCSetVal(&lp->scrl, lp->selected);
  601.       }
  602.     }
  603.  
  604.     /* if it's not visible, put it on the bottom line */
  605.     else {
  606.       lp->selected = lp->scrl.val + lp->nlines - 1;
  607.       if (lp->selected >= lp->nstr) lp->selected = lp->nstr - 1;
  608.       drawSel(lp, lp->selected);
  609.     }
  610.   }
  611.     
  612.   else if (key==LS_LINEDOWN)   {
  613.     /* if the selected item visible, but not the bottom line */
  614.     if (lp->selected >= lp->scrl.val && 
  615.     lp->selected < lp->scrl.val + lp->nlines - 1) {
  616.       if (lp->selected < lp->nstr-1) {
  617.     /* then just move it */
  618.     lp->selected++;
  619.     drawSel(lp, lp->selected);  drawSel(lp, lp->selected-1);
  620.       }
  621.     }
  622.  
  623.     /* if it's the bottom line... */
  624.     else if (lp->selected == lp->scrl.val + lp->nlines - 1) {
  625.       if (lp->selected < lp->nstr-1) {
  626.     lp->selected++;
  627.     SCSetVal(&lp->scrl, lp->scrl.val+1);
  628.       }
  629.     }
  630.  
  631.     /* if it's not visible, put it on the top line */
  632.     else {
  633.       lp->selected = lp->scrl.val;
  634.       drawSel(lp, lp->selected);
  635.     }
  636.   }
  637. }
  638.  
  639.  
  640.